package org.example.travel_web.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import jakarta.annotation.Resource;
import org.example.travel_web.dto.PageResult;
import org.example.travel_web.dto.news.*;
import org.example.travel_web.entity.CommentsET;
import org.example.travel_web.entity.NewsCategoriesET;
import org.example.travel_web.entity.NewsET;
import org.example.travel_web.entity.UserAttrET;
import org.example.travel_web.enums.Type;
import org.example.travel_web.exception.RunException;
import org.example.travel_web.mapper.CommentsMapper;
import org.example.travel_web.mapper.NewsMapper;
import org.example.travel_web.service.NewsService;
import org.example.travel_web.service.UserAttrService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author 23591
 * @description 针对表【travel_news(用于存储旅游资讯文章的信息)】的数据库操作Service实现
 * @createDate 2025-01-21 15:57:56
 */
@Service
public class NewsServiceImpl extends ServiceImpl<NewsMapper, NewsET>
        implements NewsService {

    @Resource
    private NewsMapper newsMapper;
    @Resource
    private CommentsMapper commentMapper;
    @Resource
    private UserAttrService userAttrService;

    @Override
    public PageResult<PageResp> pageResult(PageReq req) {
        MPJLambdaWrapper<NewsET> wrapper = new MPJLambdaWrapper<NewsET>()
                .selectAll(NewsET.class)
                .selectAs(NewsCategoriesET::getName, PageResp::getCategoryName)
                .leftJoin(NewsCategoriesET.class, NewsCategoriesET::getCategoryId, NewsET::getCategoryId);
        if (StrUtil.isNotBlank(req.getKeyword())) {
            wrapper.like(NewsET::getTitle, req.getKeyword());
        }
        if (req.getCategoryId() != null) {
            wrapper.eq(NewsET::getCategoryId, req.getCategoryId());
        }
        wrapper.orderByDesc(NewsET::getCreatedAt);
        Page<PageResp> page = newsMapper.selectJoinPage(new Page<>(req.getPage(), req.getSize()), PageResp.class, wrapper);
        return PageResult.of(page.getTotal(), page.getCurrent(), page.getSize(), page.getRecords());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteNews(Integer[] ids) {
        if (!removeByIds(List.of(ids))) {
            throw new RunException("删除失败");
        }
        LambdaQueryWrapper<CommentsET> wrapper = new LambdaQueryWrapper<CommentsET>()
                .eq(CommentsET::getType, Type.NEWS)
                .in(CommentsET::getRelateId, List.of(ids));
        if (commentMapper.selectCount(wrapper) > 0 && commentMapper.delete(wrapper) < 1) {
            throw new RunException("删除失败");
        }
        LambdaQueryWrapper<UserAttrET> attrWrapper = new LambdaQueryWrapper<>();
        attrWrapper.eq(UserAttrET::getType, Type.NEWS);
        attrWrapper.in(UserAttrET::getRelateId, List.of(ids));
        if (userAttrService.count(attrWrapper) > 0 && !userAttrService.remove(attrWrapper)) {
            throw new RunException("删除失败");
        }

    }

    @Override
    public void addNews(NewsReq req) {
        LambdaQueryWrapper<NewsET> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(NewsET::getTitle, req.getTitle());
        if (exists(queryWrapper)) {
            throw new RunException("标题已存在");
        }
        NewsET newsET = BeanUtil.toBean(req, NewsET.class);
        if (!save(newsET)) {
            throw new RunException("新增失败");
        }
    }

    @Override
    public void updateNews(NewsReq req) {
        if (req.getArticleId() == null) {
            throw new RunException("文章id不能为空");
        }
        LambdaQueryWrapper<NewsET> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(NewsET::getTitle, req.getTitle())
                .ne(NewsET::getArticleId, req.getArticleId());
        if (exists(queryWrapper)) {
            throw new RunException("标题已存在");
        }
        NewsET newsET = BeanUtil.toBean(req, NewsET.class);
        if (!updateById(newsET)) {
            throw new RunException("修改失败");
        }
    }

    @Override
    public NewsDetail getNewsDetail(Integer id) {
        MPJLambdaWrapper<NewsET> wrapper = new MPJLambdaWrapper<NewsET>()
                .selectAll(NewsET.class)
                .selectAll(NewsCategoriesET.class)
                .selectAs(NewsCategoriesET::getName, NewsDetail::getCategoryName);
        wrapper.eq(NewsET::getArticleId, id)
                .leftJoin(NewsCategoriesET.class, NewsCategoriesET::getCategoryId, NewsET::getCategoryId);
        NewsDetail newsDetail = newsMapper.selectJoinOne(NewsDetail.class, wrapper);
        if (newsDetail == null) {
            throw new RunException("文章不存在");
        }
        // 如果是用户 查询是否收藏
        if (StpUtil.isLogin()) {
            LambdaQueryWrapper<UserAttrET> newsWrapper = new LambdaQueryWrapper<>();
            newsWrapper.eq(UserAttrET::getUid, StpUtil.getLoginIdAsLong());
            newsWrapper.eq(UserAttrET::getType, Type.NEWS);
            newsWrapper.eq(UserAttrET::getRelateId, id);
            newsDetail.setIsCollection(userAttrService.exists(newsWrapper));
        }
        return newsDetail;
    }

    @Override
    public PageResult<UserNewsPageResp> userPageResult(UserNewsPageReq req) {
        LambdaQueryWrapper<NewsET> wrapper = new LambdaQueryWrapper<>();
        if (req.getCategoryId() != null) {
            wrapper.eq(NewsET::getCategoryId, req.getCategoryId());
        }
        if (StrUtil.isNotBlank(req.getKeyword())) {
            wrapper.like(NewsET::getTitle, req.getKeyword());
        }
        wrapper.orderByDesc(NewsET::getCreatedAt);
        Page<NewsET> page = page(new Page<>(req.getPage(), req.getSize()), wrapper);
        return PageResult.of(page.getTotal(), page.getCurrent(), page.getSize(), BeanUtil.copyToList(page.getRecords(), UserNewsPageResp.class));
    }
}




